package com.lgmshare.component.utils;

import android.text.TextUtils;

import com.lgmshare.component.annotation.NotNull;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符类处理工具类
 *
 * @author: lim
 * @description: 字符类处理工具类
 * @email: lgmshare@gmail.com
 * @datetime 2014-6-3  上午09:41:55
 */
public class StringUtils {

    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private StringUtils() {
    }

    /**
     * 判断字符串是否为有效字符串（不为空字符串）
     *
     * @param str 待判断字符串
     * @return true:有效字符串 false:无效字符串
     */
    public static boolean isValid(String str) {
        return !(null == str || "".equals(str) || "null".equals(str));
    }

    /**
     * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串 若输入字符串为null或空字符串，返回true
     *
     * @param str
     * @return boolean
     */
    public static boolean isEmpty(String str) {
        if (str == null || str.length() == 0) {
            return true;
        }
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
                return false;
            }
        }
        return true;
    }

    /**
     * 去掉字符空格，换行符等
     *
     * @param str
     * @return
     */
    public static String trimSpace(String str) {
        if (str != null) {
            str = str.replaceAll("\r", "");
            str = str.replaceAll("\n", "");
            str = str.replace(" ", "");
        }
        return str;
    }

    /**
     * 字符串转整数
     *
     * @param str
     * @return
     */
    public static int parseInt(String str) {
        if (isEmpty(str)) {
            return 0;
        }
        try {
            return Integer.parseInt(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 字符串转double
     *
     * @param str
     * @return 转换异常返回 0
     */
    public static double parseDouble(String str) {
        if (isEmpty(str)) {
            return 0;
        }
        try {
            return Double.valueOf(str.trim());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 字符串转float
     *
     * @param str
     * @return 转换异常返回 0
     */
    public static float parseFloat(String str) {
        if (isEmpty(str)) {
            return 0;
        }
        try {
            return Float.valueOf(str.trim());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 字符串转长整型
     *
     * @param str
     * @return 转换异常返回 0
     */
    public static long parseLong(String str) {
        if (isEmpty(str)) {
            return 0;
        }
        try {
            return Long.parseLong(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 字符串转布尔值
     *
     * @param str
     * @return 转换异常返回 false
     */
    public static boolean parseBoolean(String str) {
        if (isEmpty(str)) {
            return false;
        }
        try {
            return Boolean.parseBoolean(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 首字母大写
     *
     * @param s 待转字符串
     * @return 首字母大写字符串
     */
    public static String upperFirstLetter(String s) {
        if (isEmpty(s) || !Character.isLowerCase(s.charAt(0))) {
            return s;
        }
        return (char) (s.charAt(0) - 32) + s.substring(1);
    }

    /**
     * 首字母小写
     *
     * @param s 待转字符串
     * @return 首字母小写字符串
     */
    public static String lowerFirstLetter(String s) {
        if (isEmpty(s) || !Character.isUpperCase(s.charAt(0))) {
            return s;
        }
        return (char) (s.charAt(0) + 32) + s.substring(1);
    }

    /**
     * 反转字符串
     *
     * @param s 待反转字符串
     * @return 反转字符串
     */
    public static String reverse(String s) {
        int len = s.length();
        if (len <= 1) {
            return s;
        }
        int mid = len >> 1;
        char[] chars = s.toCharArray();
        char c;
        for (int i = 0; i < mid; ++i) {
            c = chars[i];
            chars[i] = chars[len - i - 1];
            chars[len - i - 1] = c;
        }
        return new String(chars);
    }

    /**
     * 转化为半角字符
     *
     * @param s 待转字符串
     * @return 半角字符串
     */
    public static String toDBC(String s) {
        if (isEmpty(s)) {
            return s;
        }
        char[] chars = s.toCharArray();
        for (int i = 0, len = chars.length; i < len; i++) {
            if (chars[i] == 12288) {
                chars[i] = ' ';
            } else if (65281 <= chars[i] && chars[i] <= 65374) {
                chars[i] = (char) (chars[i] - 65248);
            } else {
                chars[i] = chars[i];
            }
        }
        return new String(chars);
    }

    /**
     * 转化为全角字符
     *
     * @param s 待转字符串
     * @return 全角字符串
     */
    public static String toSBC(String s) {
        if (isEmpty(s)) {
            return s;
        }
        char[] chars = s.toCharArray();
        for (int i = 0, len = chars.length; i < len; i++) {
            if (chars[i] == ' ') {
                chars[i] = (char) 12288;
            } else if (33 <= chars[i] && chars[i] <= 126) {
                chars[i] = (char) (chars[i] + 65248);
            } else {
                chars[i] = chars[i];
            }
        }
        return new String(chars);
    }

    /**
     * byteArr转hexString
     * <p>例如：</p>
     * bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8
     *
     * @param bytes 字节数组
     * @return 16进制大写字符串
     */
    public static String bytes2Hex(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        int len = bytes.length;
        if (len <= 0) {
            return null;
        }
        char[] ret = new char[len << 1];
        for (int i = 0, j = 0; i < len; i++) {
            ret[j++] = DIGITS[bytes[i] >>> 4 & 0x0f];
            ret[j++] = DIGITS[bytes[i] & 0x0f];
        }
        return new String(ret);
    }

    /**
     * hexString转byteArr
     * <p>例如：</p>
     * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }
     *
     * @param hexString 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hex2Bytes(String hexString) {
        if (TextUtils.isEmpty(hexString)) {
            return null;
        }
        int len = hexString.length();
        if (len % 2 != 0) {
            hexString = "0" + hexString;
            len = len + 1;
        }
        char[] hexBytes = hexString.toUpperCase().toCharArray();
        byte[] ret = new byte[len >> 1];
        for (int i = 0; i < len; i += 2) {
            ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
        }
        return ret;
    }

    /**
     * hexChar转int(字符转数值)
     *
     * @param hexChar hex单个字节
     * @return 0..15
     */
    private static int hex2Dec(char hexChar) {
        if (hexChar >= '0' && hexChar <= '9') {
            return hexChar - '0';
        } else if (hexChar >= 'A' && hexChar <= 'F') {
            return hexChar - 'A' + 10;
        } else {
            throw new IllegalArgumentException();
        }
    }

    /**
     * HEX编码 将形如0x12 0x2A 0x01 转换为122A01
     *
     * @param bytes 待转换数据
     * @return 转换后数据
     */
    public static String hexEncode(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String tmp = Integer.toHexString(bytes[i] & 0xff);
            if (tmp.length() < 2) {
                buffer.append('0');
            }
            buffer.append(tmp);
        }
        String retStr = buffer.toString().toUpperCase(Locale.getDefault());
        return retStr;
    }

    /**
     * HEX解码 将形如122A01 转换为0x12 0x2A 0x01
     *
     * @param str 待转换数据
     * @return 转换后数据
     */
    public static byte[] hexDecode(String str) {
        if (str == null) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        for (int i = 0; i < str.length(); i += 2) {
            String onebyte = str.substring(i, i + 2);
            int b = Integer.parseInt(onebyte, 16) & 0xff;
            out.write(b);
        }
        return out.toByteArray();
    }

    /**
     * byte[]转字符串
     *
     * @param bytes
     * @return
     */
    public static String bytesToString(byte[] bytes) {
        String result = "";
        if (bytes == null) {
            return result;
        }
        return new String(bytes);
    }

    /**
     * byte[]转字符串
     *
     * @param bytes
     * @param encode 编码方式
     * @return
     */
    public static String bytesToString(byte[] bytes, String encode) {
        String result = "";
        if (bytes == null) {
            return result;
        }
        try {
            result = new String(bytes, encode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 字符串转byte[] （默认UTF-8编码）
     *
     * @param str
     * @return
     */
    public static byte[] stringToBytes(@NotNull String str) {
        byte[] result = null;
        if (str == null) {
            return result;
        }
        return str.getBytes();
    }

    /**
     * 字符串转byte[]
     *
     * @param str
     * @param encode 编码方式
     * @return
     */
    public static byte[] stringToBytes(@NotNull String str, @NotNull String encode) {
        byte[] result = null;
        if (str == null) {
            return result;
        }
        try {
            result = str.getBytes(encode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    private static final String[] UNITS = {"", "十", "百", "千", "万", "十万", "百万", "千万", "亿", "十亿", "百亿", "千亿", "万亿"};
    private static final char[] NUMBERS = {'零', '一', '二', '三', '四', '五', '六', '日', '八', '九'};

    /**
     * 将传入的金额格式化为元,保留两位小数
     *
     * @param amount （单位元）
     * @return 例如：传入5 返回5.00
     */
    public static String formatMoney(double amount) {
        DecimalFormat df = new DecimalFormat();
        df.applyPattern("###,###,###,##0.00");
        return df.format(amount);
    }

    /**
     * 将传入的金额格式化为元，保留两位小数 格式如：5.00
     *
     * @param amount 金额（单位元）
     * @return
     */
    public static String formatMoney(String amount) {
        if (TextUtils.isEmpty(amount)) {
            return "0.00";
        }
        String result;
        try {
            double num = Double.parseDouble(amount);
            result = formatMoney(num);
        } catch (NumberFormatException e) {
            result = amount;
        }
        return result;
    }

    /**
     * 将传入的金额格式化为元，保留两位小数 格式如：5.00
     *
     * @param amount 金额（单位分）
     * @return
     */
    public static String formatMoneyCent(double amount) {
        return formatMoney(amount / 100.0d);
    }

    /**
     * 将传入的金额格式化为元，保留两位小数 格式如：5.00
     *
     * @param amount 金额（单位分）
     * @return
     */
    public static String formatMoneyCent(String amount) {
        if (TextUtils.isEmpty(amount)) {
            return "0.00";
        }
        String result;
        try {
            double num = Double.parseDouble(amount);
            result = formatMoney(num / 100.0d);
        } catch (NumberFormatException e) {
            result = amount;
        }
        return result;
    }

    /**
     * 将传入的金额格式化为元,保留两位小数
     *
     * @param amount （单位元）
     * @return 附加¥
     */
    public static String formatMoneyUnit(String amount) {
        if (TextUtils.isEmpty(amount)) {
            return "0.00";
        }
        String result;
        try {
            double num = Double.parseDouble(amount);
            result = formatMoneyUnit(num);
        } catch (NumberFormatException e) {
            result = amount;
        }
        return result;
    }

    /**
     * 将传入的金额格式化为元,保留两位小数
     *
     * @param amount （单位元）
     * @return 附加¥
     */
    public static String formatMoneyUnit(double amount) {
        DecimalFormat df = new DecimalFormat();
        df.applyPattern("¥###,###,###,##0.00");
        return df.format(amount);
    }

    /**
     * 将传入的金额格式化为元，保留两位小数 格式如：¥5.00
     *
     * @param amount 金额（单位分）
     * @return
     */
    public static String formatMoneyCentUnit(String amount) {
        if (TextUtils.isEmpty(amount)) {
            return "0.00";
        }
        String result;
        try {
            double num = Double.parseDouble(amount);
            result = formatMoneyUnit(num / 100.0d);
        } catch (NumberFormatException e) {
            result = amount;
        }
        return result;
    }

    /**
     * 将传入的金额格式化为元，保留两位小数 格式如：¥5.00
     *
     * @param amount 金额（单位分）
     * @return
     */
    public static String formatMoneyCentUnit(double amount) {
        return formatMoneyUnit(amount / 100.0d);
    }

    /**
     * 手机号码分组格式化
     *
     * @param mobile 手机号码
     * @return 136 8888 8888
     */
    public static String formatMobileGroup(String mobile) {
        if (mobile.length() != 11) {
            return mobile;
        }
        //匹配电话号码格式的正则表达式...
        Pattern regex = Pattern.compile("^\\(?([0-9]{3})\\)?[-. ]?([0-9]{4})[-.?]?([0-9]{4}){1}");
        //需要匹配的目标串...
        String formattedNumber = "";
        Matcher regexMatcher = regex.matcher(mobile);
        if (regexMatcher.find()) {
            //使用捕获分组的信息来进行格式化...
            formattedNumber = regexMatcher.replaceAll("($1) $2-$3");
        }
        return formattedNumber;
    }

    /**
     * 手机号码中间4位加星号
     *
     * @param mobile 手机号码
     * @return 136****8888
     */
    public static String formatMobileStar(String mobile) {
        if (TextUtils.isEmpty(mobile)) {
            return "";
        }
        if (mobile.length() < 11) {
            return mobile;
        }
        return mobile.substring(0, 3) + "****" + mobile.substring(7, 11);
    }

    /**
     * 格式化银行卡 加*
     * 3749 **** **** 330
     *
     * @param cardNo 银行卡
     * @return 3749 **** **** 330
     */
    public static String formatCard(String cardNo) {
        if (cardNo.length() < 8) {
            return "银行卡号有误";
        }
        String card = "";
        card = cardNo.substring(0, 4) + " **** **** ";
        card += cardNo.substring(cardNo.length() - 4);
        return card;
    }

    /**
     * 通用型-文本内容加星
     *
     * @param userName userName
     * @return
     */
    public static String formatStar(String userName) {
        String userNameAfterReplaced;
        int nameLength = userName.length();
        if (nameLength < 3 && nameLength > 0) {
            if (nameLength == 1) {
                userNameAfterReplaced = "*";
            } else {
                userNameAfterReplaced = userName.substring(0, 1) + "*";
            }
        } else if (RegexUtils.isEmail(userName)) {
            String prefix = userName.substring(0, userName.indexOf("@"));
            String suffix = userName.substring(userName.indexOf("@"), nameLength);
            userNameAfterReplaced = formatStar(prefix) + suffix;
        } else {
            Integer num1, num2, num3;
            num1 = (new Double(Math.floor(new Double(nameLength) / 3))).intValue();
            num2 = (new Double(Math.ceil(new Double(nameLength) / 3))).intValue();
            num3 = nameLength - num1 - num2;
            String star = repeat('*', num2);
            userNameAfterReplaced = userName.replaceAll("(.{" + num1 + "})(.{" + num2 + "})(.{" + num3 + "})", "$1" + star + "$3");
        }
        return userNameAfterReplaced;
    }

    public static String repeat(final char ch, final int length) {
        if (length <= 0) {
            return "";
        }
        final char[] buf = new char[length];
        for (int i = length - 1; i >= 0; i--) {
            buf[i] = ch;
        }
        return new String(buf);
    }

    /**
     * 自动适配单位
     *
     * @param size
     * @return
     */
    public static String formatFileSize(long size) {
        if (size < 0) {
            return "shouldn't be less than zero!";
        } else if (size < 1024) {//KB
            return String.format(Locale.getDefault(), "%.0fB", (double) size);
        } else if (size < 1048576) {//MB
            return String.format(Locale.getDefault(), "%.0fKB", (double) size / 1024);
        } else if (size < 1073741824) {//GB
            return String.format(Locale.getDefault(), "%.1fMB", (double) size / 1048576);
        } else {
            return String.format(Locale.getDefault(), "%.2fGB", (double) size / 1073741824);
        }
    }

    /**
     * 以Mb为单位保留两位小数
     *
     * @param dirSize
     * @return
     */
    public static String formatFileMbSize(long dirSize) {
        double size = 0;
        size = (dirSize + 0.0) / (1024 * 1024);
        DecimalFormat df = new DecimalFormat("0.00");// 以Mb为单位保留两位小数
        String fileSize = df.format(size);
        return fileSize + "MB";
    }

    /**
     * 以KB为单位保留两位小数
     *
     * @param dirSize
     * @return
     */
    public static String formatFileKBSize(long dirSize) {
        double size = 0;
        size = (dirSize + 0.0) / 1024;
        DecimalFormat df = new DecimalFormat("0.00");// 以KB为单位保留两位小数
        String fileSize = df.format(size);
        return fileSize + "KB";
    }

    /**
     * 阿拉伯数字转汉字
     *
     * @param num
     * @return
     */
    public static String formatInteger(int num) {
        char[] val = String.valueOf(num).toCharArray();
        int len = val.length;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) {
            String m = val[i] + "";
            int n = Integer.valueOf(m);
            boolean isZero = n == 0;
            String unit = UNITS[(len - 1) - i];
            if (isZero) {
                if ('0' == val[i - 1]) {
                    // not need process if the last digital bits is 0
                    continue;
                } else {
                    // no unit for 0
                    sb.append(NUMBERS[n]);
                }
            } else {
                sb.append(NUMBERS[n]);
                sb.append(unit);
            }
        }
        return sb.toString();
    }

    /**
     * 阿拉伯数字转汉字
     *
     * @param decimal
     * @return
     */
    public static String formatDecimal(double decimal) {
        String decimals = String.valueOf(decimal);
        int decIndex = decimals.indexOf(".");
        int integ = Integer.valueOf(decimals.substring(0, decIndex));
        int dec = Integer.valueOf(decimals.substring(decIndex + 1));
        String result = formatInteger(integ) + "点" + formatFractionalPart(dec);
        return result;
    }

    /**
     * 阿拉伯数字转汉字(小数部分)
     */
    public static String formatFractionalPart(int decimal) {
        char[] val = String.valueOf(decimal).toCharArray();
        int len = val.length;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) {
            int n = Integer.valueOf(val[i] + "");
            sb.append(NUMBERS[n]);
        }
        return sb.toString();
    }

    /**
     * @param distance     距离
     * @param displayMeter 是否带单位（单位：m）
     * @return
     */
    public static String formatDistance(double distance, boolean displayMeter) {
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        if (distance < 1000) {
            return decimalFormat.format(distance) + (displayMeter ? "米" : "");
        } else {
            return decimalFormat.format(distance / 1000) + (displayMeter ? "千米" : "");
        }
    }

}
